class MyPromise {
  static PENDING = 'pending'
  static FULFILLED = 'fulfilled'
  static REJECTED = 'rejected'
  
  constructor(executor) {
    this.status = MyPromise.PENDING
    this.value = null
    this.callbacks = []
    try {
      executor(this.resolve, this.reject)
    } catch (err) {
      this.reject(err)
    }
  }
  
  // 状态为成功
  resolve = (value) => {
    // 状态只能改变一次，状态未改变过才能执行以下代码改变状态
    if (this.status === MyPromise.PENDING) {
      this.status = MyPromise.FULFILLED
      this.value = value
      setTimeout(() => {
        this.callbacks.map(callback => {
          callback.onFulFilled(value)
        })
      })
    }
  }
  
  // 状态为失败
  reject = (reason) => {
    // 状态只能改变一次，状态未改变过才能执行以下代码改变状态
    if (this.status === MyPromise.PENDING) {
      this.status = MyPromise.REJECTED
      this.value = reason
      setTimeout(() => {
        this.callbacks.map(callback => {
          callback.onRejected(reason)
        })
      })
    }
  }
  
  // then实例方法
  then = (onFulFilled, onRejected) => {
    // 如果onFulFilled/onRejected不是函数，将其转化成函数
    if (typeof onFulFilled !== "function") {
      onFulFilled = () => this.value
    }
    
    if (typeof onRejected !== "function") {
      onRejected = () => this.value
    }
    
    // 链式调用
    let promise = new MyPromise((resolve, reject) => {
      // 如果改变状态是在异步函数中，将需要改变的状态放入callbacks中
      if (this.status === MyPromise.PENDING) {
        this.callbacks.push({
          onFulFilled: value => {
            this.parse(promise, onFulFilled(value), resolve, reject)
          },
          onRejected: reason => {
            this.parse(promise, onRejected(reason), resolve, reject)
          }
        })
      }
      
      // 成功
      if (this.status === MyPromise.FULFILLED) {
        // 将任务放到队列中，防止阻塞
        setTimeout(() => {
          this.parse(promise, onFulFilled(this.value), resolve, reject)
        }, 0)
      }
      
      // 失败
      if (this.status === MyPromise.REJECTED) {
        // 将任务放到队列中，防止阻塞
        setTimeout(() => {
          this.parse(promise, onRejected(this.value), resolve, reject)
        }, 0)
      }
      
    })
    return promise
  };
  
  parse = (promise, res, resolve, reject) => {
    // 当链式调用时，返回的是自身，主动报错
    if (promise === res) {
      throw ('TypeError: Chaining cycle detected for promise #<Promise>')
    }
    
    try {
      if (res instanceof MyPromise) {
        res.then(value => {
          resolve(value)
        }, reason => {
          reject(reason)
        })
      } else {
        resolve(value)
      }
    } catch (err) {  //捕获错误
      reject(err)
    }
  }
  
  // 静态方法resolve
  static resolve = (value) => {
    return new MyPromise((resolve, reject) => {
      if (value instanceof MyPromise) {
        value.then(resolve, reject)
      } else {
        resolve(value)
      }
    })
  }
  
  static reject = (reason) => {
    return new MyPromise((resolve, reject) => {
      if (reason instanceof MyPromise) {
        reason.then(resolve, reject)
      } else {
        reject(reason)
      }
    })
  }
  
  static all = (promises) => {
    let values = []
    return new MyPromise((resolve, reject) => {
      promises.forEach(promise => {
        promise.then(value => {
          values.push(value)
          if (values.length === promises.length) {
            resolve(values)
          }
        }, reason => {
          resolve(reason)
        })
      })
    })
  }
  
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.map(promise => {
        promise.then(value => {
          resolve(value)
        }, reason => {
          reject(reason)
        })
        
      })
    })
  }
}

